package com.grq.mis.satoken;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.grq.mis.component.RbacComponent;
import com.grq.mis.dao.DepartmentDao;
import com.grq.mis.dao.UserDao;
import com.grq.mis.entity.Department;
import com.grq.mis.entity.User;
import com.grq.mis.exception.BusinessException;
import com.grq.mis.exception.ResultEnum;
import com.grq.mis.model.sys.Me;
import com.grq.mis.model.view.Menu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
public class SaTokenRealm {

    public static final String LOGIN_CLIENT = "web";
    public static final int MAX_LOGIN_ERROR_COUNT = 10;

    @Autowired
    private UserDao userDao;
    @Autowired
    private RbacComponent rbacComponent;
    @Autowired
    private DepartmentDao departmentDao;

    /**
     * 登录验证
     *
     * @param username
     * @param password
     */
    public void login(String username, String password) {

        // 根据用户名获取用户信息
        User user = userDao.createLambdaQuery().andEq(User::getUsername, username).orEq(User::getPhone,username).single();

        // 用户不存在
        if (user == null) {
            throw new BusinessException(ResultEnum.USERNAME_IS_NOT_EXIST);
        }

        // 达到错误次数
        int loginErrorCount = rbacComponent.getLoginErrorCount(user.getId());
        if (loginErrorCount >= MAX_LOGIN_ERROR_COUNT) {
            rbacComponent.addLoginRecord(user.getUsername(), LOGIN_CLIENT, false, ResultEnum.PASSWORD_ERROR_COUNT_OVER.getMsg());
            throw new BusinessException(ResultEnum.PASSWORD_ERROR, ResultEnum.PASSWORD_ERROR_COUNT_OVER.getMsg() + ",请稍后再试");
        }

        // 密码错误
        if (!DigestUtil.bcryptCheck(password, user.getPassword())) {
            rbacComponent.addLoginErrorCount(user.getId());
            rbacComponent.addLoginRecord(user.getUsername(), LOGIN_CLIENT, false, ResultEnum.PASSWORD_ERROR.getMsg());
            throw new BusinessException(ResultEnum.PASSWORD_ERROR);
        }

        // 账号停用
        if (user.getIsDisable() == true) {
            rbacComponent.addLoginRecord(user.getUsername(), LOGIN_CLIENT, false, ResultEnum.USER_IS_DISABLED.getMsg());
            throw new BusinessException(ResultEnum.USER_IS_DISABLED);
        }

        // 设置登录
        StpUtil.login(user.getId());

        SaSession ss = StpUtil.getSession();

        // 登录信息
        Me me = new Me();

        me.setId(user.getId());
        me.setUsername(user.getUsername());
        me.setName(user.getName());
        me.setCompany(user.getCompany());
        me.setPhone(user.getPhone());

        if (user.getDepartmentId() != null){
            Department department = departmentDao.single(user.getDepartmentId());
            if (department != null){
                me.setDepartmentId(department.getId());
                me.setDepartmentName(department.getName());
            }
        }

        ss.setAttribute("me", me);

        // 权限
        List<String> permissions = rbacComponent.findPermissionCodeByUserId(user.getId());
        ss.setAttribute("permissions", permissions);

        // 角色
        List<String> roles = rbacComponent.findRoleCodeByUserId(user.getId());
        ss.setAttribute("roles", roles);

        // 菜单
        List<Menu> menus = new ArrayList<>();
        if (permissions.size() > 0) {
            menus = rbacComponent.findMenusByPermissionCode(permissions);
        }
        if (menus == null) {
            menus = new ArrayList<>();
        }
        ss.setAttribute("menus", menus);

        // 登录成功日志
        rbacComponent.addLoginRecord(user.getUsername(), LOGIN_CLIENT, true, "登录成功");
        // 清除登录错误次数
        rbacComponent.clearLoginErrorCount(user.getId());
    }

}
